package com.cskaoyan.config.shiro;

import com.cskaoyan.config.shiro.CustomSessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.util.LinkedHashMap;

/**
 * ClassName: ShiroConfiguration
 * Description:
 * date: 2022/6/6 17:12
 *
 * @author bruce
 * @since JDK 8
 */
@Configuration
public class ShiroConfiguration {

    //ShiroFilter → 依赖于SecurityManager
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 如果想要修改重定向的地址
        // 将重定向url设置为匿名请求，并且响应认证失败的json数据
       // shiroFilterFactoryBean.setLoginUrl("/redirect");

        // shiro管理的内部的filter：anon、authc、perms
        // Filter是谁, filter的作用范围是什么，filter的顺序是什么
        // LinkedHashMap
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        filterChainDefinitionMap.put("/redirect", "anon");


        filterChainDefinitionMap.put("/admin/storage/**", "anon");

        filterChainDefinitionMap.put("/admin/admin/list","anon");
        filterChainDefinitionMap.put("/admin/admin/add","anon");
        // 这个请求就是登陆请求 → 把当前用户（Subject）变为已经认证的状态
        filterChainDefinitionMap.put("/admin/auth/login", "anon");
        filterChainDefinitionMap.put("/admin/auth/info", "anon");
        filterChainDefinitionMap.put("/admin/**","authc");

        // 权限是和URL绑定的，url绑定了Handler方法 → Handler方法和权限绑定
        // filterChainDefinitionMap.put("/admin/user/list", "perms[admin:user:list]");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    //SecurityManager →依赖于realm、SessionManager、默认的认证器和授权器
    @Bean
    public DefaultWebSecurityManager securityManager(CustomRealm realm, DefaultWebSessionManager sessionManager) {
        // 如果没有使用setAuthenticator、没有使用setAuthorizer方法，使用的就是默认的认证器和授权器
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(realm);

        defaultWebSecurityManager.setSessionManager(sessionManager);
        return defaultWebSecurityManager;
    }

    //realms → extends AuthorizingRealm

    //SessionManager
    //前后端分离的应用 → 跨域 → Session发生变化
    //shiro中的信息是通过Session来维护的，而如果Session发生变化了，信息就拿不到了
    @Bean
    public DefaultWebSessionManager sessionManager() {
        return new CustomSessionManager();
    }

    // 用到AspectJ → 使用注解的方式，将权限和url绑定起来
    @Bean
    @Order(0)
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
